package com.jprocms.module.cms.service.operate;

import com.jpro.framework.security.core.util.SecurityFrameworkUtils;
import com.jprocms.module.cms.controller.portal.vo.OperateCreateReqVO;
import com.jprocms.module.cms.controller.portal.vo.OperateQueryReqVO;
import com.jprocms.module.cms.convert.operate.OperateConvert;
import com.jprocms.module.cms.dal.dataobject.operate.OperateDO;
import com.jprocms.module.cms.dal.dataobject.site.SiteDO;
import com.jprocms.module.cms.dal.mysql.operate.OperateMapper;
import com.jprocms.module.cms.enums.EnumFrontOperate;
import com.jprocms.module.cms.enums.EnumFrontOperateQueryType;
import com.jprocms.module.cms.util.CmsContextUtil;
import com.jprocms.module.cms.util.RequestUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.List;

import static com.jpro.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.jprocms.module.cms.enums.ErrorCodeConstants.OPERATE_NOT_EXISTS;

/**
 * 操作记录 Service 实现类
 *
 * @author JPROCMS
 */
@Service
@Validated
public class OperateServiceImpl implements OperateService {

    @Resource
    private OperateMapper operateMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createOperate(OperateCreateReqVO createReqVO) {
        // 插入
        OperateDO operate = OperateConvert.INSTANCE.convert(createReqVO);
        operateMapper.insert(operate);
        // 返回
        return operate.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOperate(Long id) {
        // 校验存在
        validateOperateExists(id);
        // 删除
        operateMapper.deleteById(id);
    }

    private void validateOperateExists(Long id) {
        if (operateMapper.selectById(id) == null) {
            throw exception(OPERATE_NOT_EXISTS);
        }
    }

    @Override
    public OperateDO getOperate(Long id) {
        return operateMapper.selectById(id);
    }

    @Override
    public List<OperateDO> getOperateList(Collection<Long> ids) {
        return operateMapper.selectBatchIds(ids);
    }

    @Override
    public List<OperateDO> getOperateList(OperateQueryReqVO queryReqVO) {
        return operateMapper.selectList(queryReqVO);
    }

    @Override
    public Long getOperateCount(OperateQueryReqVO queryReqVO) {
        return operateMapper.selectCount(queryReqVO);
    }

    @Override
    public boolean existOperate(Long id, OffsetDateTime date, EnumFrontOperate operate, EnumFrontOperateQueryType enumFrontOperateQueryType,
                                HttpServletRequest request, HttpServletResponse response) {
        long cookie = RequestUtils.resolveIdentityCookie(request, response);
        String ip = RequestUtils.getRemoteAddr(request);
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        OperateQueryReqVO.OperateQueryReqVOBuilder builder = OperateQueryReqVO.builder();
        builder.opeDataId(id).opeType(operate.getType());
        if (EnumFrontOperateQueryType.ALL.equals(enumFrontOperateQueryType)) {
            builder.identityCookie(cookie).userId(userId).ip(ip);
        } else if (EnumFrontOperateQueryType.IP.equals(enumFrontOperateQueryType)) {
            builder.ip(ip);
        } else if (EnumFrontOperateQueryType.USER.equals(enumFrontOperateQueryType)) {
            builder.userId(userId);
        } else if (EnumFrontOperateQueryType.COOKIE.equals(enumFrontOperateQueryType)) {
            builder.identityCookie(cookie);
        }
        if (date != null) {
            builder.date(date);
        }
        OperateQueryReqVO reqVO = builder.build();
        //查询操作记录表
        if (getOperateCount(reqVO) > 0) {
            return true;
        }
        return false;
    }

    public void insertOperate(Long id, EnumFrontOperate operate, long cookie, String ip, Long userId) {
        SiteDO site = CmsContextUtil.getSite();
        OperateQueryReqVO.OperateQueryReqVOBuilder builder = OperateQueryReqVO.builder();
        builder.opeDataId(id).opeType(operate.getType());
        builder.identityCookie(cookie).userId(userId).ip(ip);
        OperateQueryReqVO reqVO = builder.build();
        OperateCreateReqVO operateCreateReqVO = OperateConvert.INSTANCE.convert(reqVO);
        operateCreateReqVO.setIp(ip);
        operateCreateReqVO.setSiteId(site.getId());
        createOperate(operateCreateReqVO);
    }

}
